﻿/*========================== 
 * @author 郑金泉
 * @desc 实体字段类
 * ========================= */
using System;
using System.Collections.Generic;
using System.Text;

using Obsidian.Data.Sql;
using Obsidian.Utils;

namespace Obsidian.Edm
{
    public abstract class ModelField
    {

        private DbField dbField = null;
        private IModel _model = null;
        protected bool _isNull = true;
        private bool _isList = false;

        /// <summary>
        /// 实体数据模型
        /// </summary>
        public IModel Model
        {
            get { return this._model; }
        }

        /// <summary>
        /// 是否为空
        /// </summary>
        public bool IsNull
        {
            get { return this._isNull; }
        }

        /// <summary>
        /// 是否是列表字段
        /// </summary>
        public bool IsList
        {
            get { return this._isList; }
        }

        private string _dbFieldName = null;
        /// <summary>
        /// 数据库映射字段
        /// </summary>
        public string DbFieldName
        {
            get { return this._dbFieldName; }
        }

        private string _jPropName = null;
        /// <summary>
        /// Json属性名
        /// </summary>
        public string Alias
        {
            get { return this._jPropName; }
        }

        protected bool _assigned = false;
        /// <summary>
        /// 是否已赋值的
        /// </summary>
        public bool Assigned
        {
            set { this._assigned = value; }
            get { return this._assigned; }
        }

        public void InitField(IModel model)
        {
            this._model = model;
        }

        public void InitField(IModel model, string dbFieldName)
        {
            this._model = model;
            this._dbFieldName = dbFieldName;
        }

        public void InitField(IModel model, string dbFieldName, string alias)
        {
            this._model = model;
            this._dbFieldName = dbFieldName;
            this._jPropName = alias;
        }

        public DbField GetDbField()
        {
            if (this.dbField == null)
            {
                if (String.IsNullOrEmpty(this._dbFieldName))
                    return null;

                DbTable dbTable = this.Model.GetDbTable();
                this.dbField = dbTable.GetFieldByName(this._dbFieldName);
                if (this.dbField == null)
                    throw new Exception("字段" + this._dbFieldName + "不存在。");
            }
            return this.dbField;
        }

        #region Compare

        public ISqlCondition Compare(string compareOperator, object value)
        {
            return new CompareCondition(this, compareOperator, value);
        }

        public ISqlCondition Compare(string compareOperator, ModelField targetField)
        {
            return new CompareCondition(this, compareOperator, targetField);
        }

        public ISqlCondition Equals(object value)
        {
            return new CompareCondition(this, "=", value);
        }

        public ISqlCondition Equals(ModelField targetField)
        {
            return new CompareCondition(this, "=", targetField);
        }

        #endregion


        #region In

        public ISqlCondition In(params object[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "=", values[0]);
            else
            {
                string strValues = "'" + ArrayUtil.Join(values, "','") + "'";
                return new InCondition(this, strValues);
            }
        }

        public ISqlCondition In(params string[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "=", values[0]);
            else
            {
                string strValues = "'" + ArrayUtil.Join(values, "','") + "'";
                return new InCondition(this, strValues);
            }
        }

        public ISqlCondition In(params int[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "=", values[0]);
            else
            {
                string strValues = ArrayUtil.Join(values, ",");
                return new InCondition(this, strValues);
            }
        }

        public ISqlCondition In(params long[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "=", values[0]);
            else
            {
                string strValues = ArrayUtil.Join(values, ",");
                return new InCondition(this, strValues);
            }
        }

        public ISqlCondition In<T>(ICollection<T> values)
        {
            if (values.Count == 0)
                throw new Exception("参数values长度不能为0");
            string strValues = "'" + ArrayUtil.Join<T>(values, "','") + "'";
            return new InCondition(this, strValues);
        }

        #endregion


        #region Not In

        public ISqlCondition NotIn(params object[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "<>", values[0]);
            else
            {
                string strValues = "'" + ArrayUtil.Join(values, "','") + "'";
                return new InCondition(this, InClauseKeyWord.NOT_IN, strValues);
            }
        }

        public ISqlCondition NotIn(params string[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "<>", values[0]);
            else
            {
                string strValues = "'" + ArrayUtil.Join(values, "','") + "'";
                return new InCondition(this, InClauseKeyWord.NOT_IN, strValues);
            }
        }

        public ISqlCondition NotIn(params int[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "<>", values[0]);
            else
            {
                string strValues = ArrayUtil.Join(values, ",");
                return new InCondition(this, InClauseKeyWord.NOT_IN, strValues);
            }
        }

        public ISqlCondition NotIn(params long[] values)
        {
            if (values.Length == 0)
                throw new Exception("参数values长度不能为0");
            if (values.Length == 1)
                return new CompareCondition(this, "<>", values[0]);
            else
            {
                string strValues = ArrayUtil.Join(values, ",");
                return new InCondition(this, InClauseKeyWord.NOT_IN, strValues);
            }
        }

        public ISqlCondition NotIn<T>(ICollection<T> values)
        {
            if (values.Count == 0)
                throw new Exception("参数values长度不能为0");
            string strValues = "'" + ArrayUtil.Join<T>(values, "','") + "'";
            return new InCondition(this, InClauseKeyWord.NOT_IN, strValues);
        }

        #endregion


        #region Like

        public ISqlCondition Like(string keyWord)
        {
            if (String.IsNullOrEmpty(keyWord))
                throw new Exception("参数keyWord不能为空");
            return new LikeCondition(this, keyWord);
        }

        public ISqlCondition Like(string keyWord, LikeType likeType)
        {
            if (String.IsNullOrEmpty(keyWord))
                throw new Exception("参数keyWord不能为空");
            return new LikeCondition(this, keyWord, likeType);
        }

        public ISqlCondition Like(ICollection<string> keyWords)
        {
            if (keyWords.Count == 0)
                throw new Exception("参数keyWords长度不能为0");

            CompoundCondition cc = new CompoundCondition();
            foreach (string kw in keyWords)
            {
                LikeCondition lc = new LikeCondition(LogicalOperator.OR, this, kw);
                cc.AddSubCondition(lc);
            }
            return cc;
        }

        public ISqlCondition Like(ICollection<string> keyWords, LogicalOperator logicalOperator, LikeType likeType)
        {
            if (keyWords.Count == 0)
                throw new Exception("参数keyWords长度不能为0");

            CompoundCondition cc = new CompoundCondition();
            foreach (string kw in keyWords)
            {
                LikeCondition lc = new LikeCondition(logicalOperator, this, kw, likeType);
                cc.AddSubCondition(lc);
            }
            return cc;
        }

        #endregion


        #region Between

        public ISqlCondition Between(object valStart, object valEnd)
        {
            if (valStart == null || valEnd == null)
                throw new Exception("参数valStart和valEnd不能为空!");
            return new BetweenCondition(this, valStart, valEnd);
        }

        #endregion


        #region Contanis

        public ISqlCondition Contanis(string matchingString)
        {
            if (String.IsNullOrEmpty(matchingString))
                throw new Exception("参数matchingString不能为空!");
            return new ContanisCondition(this, matchingString);
        }

        #endregion


        public virtual FieldType Type
        {
            get { return FieldType.Unknown; }
        }

    }

    public enum FieldType
    {
        Unknown,
        String,
        Int,
        Long,
        Bool,
        Double,
        DateTime,
        Decimal,
        Entity,
        IntList,
        StringList,
        LongList,
        EntityList,
        Enum,
        Order
    }
}
